#include "mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    udpSocket = new QUdpSocket;    /* UDP套接字 */
    tcpSocket = new QTcpSocket;    /* TCP套接字 */

    label[0] = new QLabel;    /* 标签文本 */
    label[1] = new QLabel;
    label[2] = new QLabel;
    label[3] = new QLabel;
    lineEdit = new QLineEdit;    /* 用于输入IP */
    spinBox = new QSpinBox;    /* 用于选择端口 */
    comboBox = new QComboBox;    /* 用于选择协议类型 */
    pushButton[0] = new QPushButton;    /* 按钮 */
    pushButton[1] = new QPushButton;

    hBoxLayout = new QHBoxLayout;    /* 水平布局 */
    vBoxLayout = new QVBoxLayout;    /* 垂直布局 */
    hWidget = new QWidget;    /* 水平容器 */
    vWidget = new QWidget;    /* 垂直容器 */

    label[0]->setText("视频监控客户端\n");    /* 填充文本 */
    label[0]->setStyleSheet("background:rgb(255,255,255); font:60px; color:rgb(200,200,200)");
    label[0]->setAlignment(Qt::AlignCenter);
    label[1]->setText("IP地址:");
    lineEdit->setText("192.168.1.1");
    label[2]->setText(" 端口:");
    spinBox->setRange(0, 65535);
    spinBox->setValue(2000);
    label[3]->setText(" 协议:");
    comboBox->addItem("UDP");
    comboBox->addItem("TCP");
    pushButton[0]->setText("连接");
    pushButton[1]->setText("断开");
    pushButton[1]->setEnabled(false);

    label[0]->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);    /* 设置控件大小策略 */
    label[0]->setMinimumSize(640, 480);
    label[1]->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
    lineEdit->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
    label[2]->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
    spinBox->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
    label[3]->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
    comboBox->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
    pushButton[0]->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
    pushButton[1]->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);

    hBoxLayout->addWidget(label[1]);    /* 设置布局 */
    hBoxLayout->addWidget(lineEdit);
    hBoxLayout->addWidget(label[2]);
    hBoxLayout->addWidget(spinBox);
    hBoxLayout->addWidget(label[3]);
    hBoxLayout->addWidget(comboBox);
    hBoxLayout->addSpacerItem(new QSpacerItem(20, 20, QSizePolicy::MinimumExpanding, QSizePolicy::Fixed));
    hBoxLayout->addWidget(pushButton[0]);
    hBoxLayout->addWidget(pushButton[1]);
    hWidget->setLayout(hBoxLayout);
    vBoxLayout->addWidget(hWidget);
    vBoxLayout->addWidget(label[0]);
    vWidget->setLayout(vBoxLayout);

    setCentralWidget(vWidget);    /* 居中显示 */

    connect(pushButton[0], SIGNAL(clicked()), this, SLOT(toConnect()));    /* 连接信号与槽 */
    connect(pushButton[1], SIGNAL(clicked()), this, SLOT(toDisconnect()));
    connect(udpSocket, SIGNAL(readyRead()), this, SLOT(udpReceiveMessages()));
    connect(tcpSocket, SIGNAL(connected()), this, SLOT(connected()));
    connect(tcpSocket, SIGNAL(disconnected()), this, SLOT(disconnected()));
    connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(tcpReceiveMessages()));
}

MainWindow::~MainWindow()
{
}

void MainWindow::toConnect()
{
    if (comboBox->currentText() == "UDP") {
        udpSocket->writeDatagram("Connect", QHostAddress(lineEdit->text()), spinBox->value());
    }
    else {
        tcpSocket->connectToHost(lineEdit->text(), spinBox->value());
    }
    connectingFlag = 1;
    QTimer::singleShot(1000, this, SLOT(connectTimeOut()));    /* 连接超时时间1秒 */
}

void MainWindow::connected()
{
    connectingFlag = 0;
    reconnectFlag = 1;
    lineEdit->setEnabled(false);
    spinBox->setEnabled(false);
    comboBox->setEnabled(false);
    pushButton[0]->setEnabled(false);
    pushButton[1]->setEnabled(true);
}

void MainWindow::connectTimeOut()
{
    if (connectingFlag == 1) {
        if (comboBox->currentText() == "TCP") {
            tcpSocket->disconnectFromHost();
        }
        connectingFlag = 0;
    }
}

void MainWindow::toDisconnect()
{
    if (comboBox->currentText() == "UDP") {
        udpSocket->writeDatagram("Disconnect", QHostAddress(lineEdit->text()), spinBox->value());
        disconnected();
        udpConnectedFlag = 0;
    }
    else {
        tcpSocket->disconnectFromHost();
    }
}

void MainWindow::disconnected()
{
    lineEdit->setEnabled(true);
    spinBox->setEnabled(true);
    comboBox->setEnabled(true);
    pushButton[0]->setEnabled(true);
    pushButton[1]->setEnabled(false);
}


void MainWindow::udpReceiveMessages()
{
    int ret;
    static QByteArray data;
    static int dataBytes;
    static QByteArray frame;
    static uint frameBytes;
    static uint readBytes;
    static int readFinish = 1;

    if (reconnectFlag == 1) {
        readFinish = 1;
        reconnectFlag = 0;
    }

    while (udpSocket->hasPendingDatagrams()) {    /* 如果有待处理的数据 */
        dataBytes = udpSocket->pendingDatagramSize();
        qDebug("dataBytes: %d", dataBytes);
        data.resize(dataBytes);
        ret = udpSocket->readDatagram(data.data(), dataBytes);    /* 读取数据 */
        if (ret <= 0)    /* 读取失败，将重新读取 */
            continue;

        if (udpConnectedFlag == 0 && connectingFlag == 1 && dataBytes == 10 && (QString)data.data() == "Connected") {    /* 已连接消息 */
            connected();
            udpConnectedFlag = 1;
        }
        else if (udpConnectedFlag == 1) {
            if (readFinish == 1) {    /* 上一帧图像的内容和帧尾已读取完成 */
                if (dataBytes == 6 && (uchar)data[0] == 0xA5 && (uchar)data[1] == 0x5A) {    /* 本帧图像的帧头 */

                    frameBytes = qFromBigEndian<uint>(data.data()+2);    /* 获取本帧图像的字节数 */
                    qDebug("frameBytes: %u", frameBytes);

                    frame.resize(0);
                    readBytes = 0;
                    readFinish = 0;    /* 即将读取本帧图像的内容和帧尾 */
                }
            }
            else {    /* 本帧图像的帧头已读取完成 */
                if (dataBytes == 2 && (uchar)data[0] == 0x5A && (uchar)data[1] == 0xA5) {    /* 本帧图像的帧尾 */
                    qDebug("readBytes: %u", readBytes);

                    QPixmap pixmap = QPixmap::fromImage(QImage::fromData(frame, "JPG"));    /* 显示本帧图像 */
                    pixmap = pixmap.scaled(label[0]->size(), Qt::KeepAspectRatio);
                    label[0]->setPixmap(pixmap);

                    readFinish = 1;    /* 即将读取下一帧图像的帧头 */
                }
                else if (readBytes < frameBytes) {
                    frame += data;    /* 追加本帧图像的内容 */
                    readBytes += dataBytes;
                }
            }
        }
    }
}

void MainWindow::tcpReceiveMessages()
{
    long ret;
    static QByteArray frame;
    static uint frameBytes;
    static uint readBytes = 0;
    static int readFinish = 1;

    if (reconnectFlag == 1) {
        readBytes = 0;
        readFinish = 1;
        reconnectFlag = 0;
    }

    while (tcpSocket->atEnd() == false) {    /* 如果有可读取的数据 */
        if (readFinish == 1) {    /* 上一帧图像的内容已读取完成 */
            ret = tcpSocket->read((char *)&frameBytes + readBytes, 4 - readBytes);    /* 读取本帧图像的字节数 */
            if (ret <= 0)    /* 读取出错，将重新读取 */
                continue;
            readBytes += ret;
            if (readBytes < 4)    /* 长度不足，将继续读取 */
                continue;

            frameBytes = qFromBigEndian<uint>(frameBytes);    /* 调整字节序 */
            frame.resize(frameBytes);    /* 本帧图像的字节数已读取完成，为frame重设大小 */
            qDebug("frameBytes: %u", frameBytes);

            readBytes = 0;
            readFinish = 0;    /* 即将读取本帧图像的内容 */
        }
        else {    /* 本帧图像的字节数已读取完成 */
            ret = tcpSocket->read(frame.data() + readBytes, frameBytes - readBytes);    /* 读取本帧图像的内容 */
            if (ret <= 0)    /* 读取出错，将重新读取 */
                continue;
            readBytes += ret;
            if (readBytes < frameBytes)    /* 长度不足，将继续读取 */
                continue;

            QPixmap pixmap = QPixmap::fromImage(QImage::fromData(frame, "JPG"));    /* 本帧图像的内容已读取完成，显示本帧图像 */
            pixmap = pixmap.scaled(label[0]->size(), Qt::KeepAspectRatio);
            label[0]->setPixmap(pixmap);

            readBytes = 0;
            readFinish = 1;    /* 即将读取下一帧图像的字节数 */
        }
    }
}


